<?php
/**
 * Nweb Framework
 *
 * This script is protected by copyright. It's use, copying, modification
 * and distribution without written consent of the author is prohibited.
 *
 * @category    source
 * @package     pl.nweb.framework.application
 * @subpackage  pl.nweb.framework.application.router
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt  GNU Lesser General Public
 * @version     3.0 $Id$
 * @link        http://code.google.com/p/nweb-framework/
 * @link        http://framework.nweb.pl
 */

namespace pl\nweb\framework\application;

/**
 * Menadżer tras
 *
 * @category    source
 * @package     pl.nweb.framework.application
 * @subpackage  pl.nweb.framework.application.router
 * @author      Krzysztof Kardasz <krzysztof.kardasz@gmail.com>
 * @copyright   Copyright (c) 2011 Krzysztof Kardasz
 * @version     3.0 $Id$
 */
class Router
{
    /**
     * Obiekt dyspozytora
     *
     * @var null|\pl\nweb\framework\application\Dispatcher
     */
    private $_dispatcher = null;

    /**
     * Obiekt żądania
     *
     * @var null|\pl\nweb\framework\application\Request
     */
    private $_request = null;

    /**
     * Opcje
     *
     * @var array
     */
    private $_options = array();

    /**
     * Kolekcja tras
     *
     * @var array
     */
    protected $_list = array();

    /**
     * Bieżąca trasa
     *
     * @var \pl\nweb\framework\application\router\Route
     */
    protected $_current = null;

    /**
     * Adres hosta (schemat+host)
     *
     * @var null|string
     */
    protected $_urlHost = null;

    /**
     * Bazowa ścieżka
     *
     * @var null|string
     */
    protected $_urlBase = null;

    /**
     * Opcje
     */
    const OPTION_DISPATCHER_OBJ = 'dispatcher.obj';
    const OPTION_REQUEST_OBJ    = 'request.obj';
    const OPTION_ADD_HOST       = 'add.host';

    /**
     * Konstruktor
     *
     * @param array $options parametry
     */
    public function __construct (array $options = array())
    {
        if(!empty($options)) {
            $this->_options = $options;
        }
    }

    /**
     * Dodaje obiek trasy
     *
     * @param \pl\nweb\framework\application\router\Route $route obiekt trasy
     * @return void
     */
    public function addRoute (router\Route $route)
    {
        $this->_list[$route->getName()] = $route;
    }

    /**
     * Zwraca trasę
     *
     * @param null|string $name nazwa trasy
     * @return null|\pl\nweb\framework\application\router\Route
     */
    public function getRoute ($name = null)
    {
        if(isset($this->_list[$name])) {
            return $this->_list[$name];
        }
        return null;
    }

    /**
     * Zwraca flagę czy trasa istnieje
     *
     * @param string $name nazwa trasy
     * @return boolean
     */
    public function hasRoute ($name)
    {
        return isset($this->_list[$name]);
    }

    /**
     * Usuwa trasę
     *
     * @param string $name nazwa trasy
     * @return boolean
     */
    public function removeRoute ($name)
    {
        if(isset($this->_list[$name])) {
            unset($this->_list[$name]);
            return true;
        }
        return false;
    }

    /**
     * Generowanie adresu url
     *
     * @param  array $params parametry trasy
     * @param  string $name nazwa trasy
     * @param  boolean $reset przepisywanie aktualnych parametrów
     * @param  array $query zapytanie (uri query string)
     * @return string
     */
    public function url ($params = array(), $name = null, $reset = false, array $query = array())
    {
        if(!$reset) {
            $params = array_merge($this->_params, $params);
            $query  = array_merge($_GET, $query);
        }
        $url = $this->getRoute($name)->url($params, $query);

        // TODO: BaseUrl
    }

    /**
     * Zwraca host http
     *
     * @return string
     */
    public function _getUrlHost ()
    {
        if(null == $this->_urlHost) {
            $scheme = $this->_getRequest()->getScheme();
            $host   = $this->_getRequest()->getHost();
            $this->_urlHost = $scheme . '://' . $host;
        }
        return $this->_urlHost;
    }

    /**
     * Definiuje obiekt żądania
     *
     * @param \pl\nweb\framework\application\Request\Http $request obiekt żądania
     * @return void
     */
    protected function _setRequest (\pl\nweb\framework\application\Request\Http $request)
    {
        $this->_request = $request;
    }

    /**
     * Zwraca obiekt żądania
     *
     * @return \pl\nweb\framework\application\Request\Http
     * @throws \pl\nweb\framework\application\router\Exception
     */
    protected function _getRequest ()
    {
        if(null === $this->_request) {
            if(isset($this->_options[self::OPTION_REQUEST_OBJ])) {
                $this->_setRequest($this->_options[self::OPTION_REQUEST_OBJ]);
            } else {
                throw new router\Exception ('Request object is not defined');
            }
        }
        return $this->_request;
    }

    /**
     * Definiuje obiekt dyspozytora
     *
     * @param \pl\nweb\framework\application\Dispatcher $dispatcher obiekt dyspozytora
     * @return void
     */
    protected function _setDispatcher (\pl\nweb\framework\application\Dispatcher $dispatcher)
    {
        $this->_dispatcher = $dispatcher;
    }

    /**
     * Zwraca obiekt dyspozytora
     *
     * @return \pl\nweb\framework\application\Dispatcher $request
     * @throws \pl\nweb\framework\application\router\Exception
     */
    protected function _getDispatcher ()
    {
        if(null === $this->_dispatcher) {
            if(isset($this->_options[self::OPTION_DISPATCHER_OBJ])) {
                $this->_setDispatcher($this->_options[self::OPTION_DISPATCHER_OBJ]);
            } else {
                throw new router\Exception ('Dispatcher object is not defined');
            }
        }
        return $this->_dispatcher;
    }
}